from ctypes import *
from CanFrame import CanFrame

USBCAN1 = 3

class _VCI_INIT_CONFIG(Structure):
    _fields_ = [('AccCode', c_ulong),
                ('AccMask', c_ulong),
                ('Reserved', c_ulong),
                ('Filter', c_ubyte),
                ('Timing0', c_ubyte),
                ('Timing1', c_ubyte),
                ('Mode', c_ubyte)]


class _VCI_CAN_OBJ(Structure):
    _fields_ = [('ID', c_uint),
                ('TimeStamp', c_uint),
                ('TimeFlag', c_byte),
                ('SendType', c_byte),
                ('RemoteFlag', c_byte),
                ('ExternFlag', c_byte),
                ('DataLen', c_byte),
                ('Data', c_byte*8),
                ('Reserved', c_byte*3)]

vic = _VCI_INIT_CONFIG()
vic.AccCode = ~0x7FE
vic.AccMask = ~0x7FF #~0x7FF #0xffffffff # 0: 有关位; 1: 无关位
# =1 表示单滤波; =0 表示双滤波
vic.Filter = 0
#  500 kbps : (Timing0,Timing1) = (0x00, 0x1C)
vic.Timing0 = 0x00
vic.Timing1 = 0x1c
# 0: normal mode; 1: listen mode
vic.Mode = 0

vco = _VCI_CAN_OBJ()
vco.ID = 0x00000001
vco.SendType = 0
vco.RemoteFlag = 0
vco.ExternFlag = 0
vco.DataLen = 8
vco.Data = (1, 2, 3, 4, 5, 6, 7, 8)

vco_rx = _VCI_CAN_OBJ()
vco.ID = 0
vco.SendType = 0
vco.RemoteFlag = 0
vco.ExternFlag = 0
vco.DataLen = 0
vco.Data = (0, 0, 0, 0, 0, 0, 0, 0)

class USBCANDllReader(object):
    def __init__(self) -> object:
        self.canLib = windll.LoadLibrary('./ControlCAN.dll') # 需要把dll文件, .h, .lib文件和kerneldlls文件放到根目录下


    def openDevice(self):
        result_str = ["失败", "成功"]
        idx = 0

        idx = self.canLib.VCI_OpenDevice(USBCAN1, 0, 0)
        print("打开设备: %s" % result_str[idx])
        if idx != 1:
            return

        idx = self.canLib.VCI_SetReference(USBCAN1, 0, 0, 4, pointer(c_int(100))) #发送重发的超时时间，单位为ms
        print("设置超时重发时间: %s" % result_str[idx])

        idx = self.canLib.VCI_SetReference(USBCAN1, 0, 0, 0, pointer(c_int(0x060007)))
        print("设置波特率: %s" % result_str[idx])

        idx = self.canLib.VCI_InitCAN(USBCAN1, 0, 0, pointer(vic))
        print("初始化: %s" % result_str[idx])

        idx = self.canLib.VCI_StartCAN(USBCAN1, 0, 0)
        print("启动: %s" % result_str[idx])

        idx = self.canLib.VCI_ClearBuffer(USBCAN1, 0, 0)
        print("清空缓冲区: %s" % result_str[idx])


    def closeDevice(self):
        print("关闭设备: %d" % self.canLib.VCI_CloseDevice(USBCAN1, 0))


    def transmit(self, text, can_frame):
        vco.ID = can_frame.can_id
        vco.DataLen = can_frame.can_dlc
        vco.Data = tuple(can_frame.can_data)

        print('%s %d' % (text, self.canLib.VCI_Transmit(USBCAN1, 0, 0, pointer(vco), 1)))
        print("Tx CanId = %x DLC = %d  "%(vco.ID, vco.DataLen), end="")
        print("Data = ", end="")
        for d in can_frame.can_data:
            print("%X "%d, end="")
        print()


    def receive(self):
        rev_num = self.canLib.VCI_GetReceiveNum(USBCAN1, 0, 0)
        print("接收帧数量: %d" % rev_num)

        can_frame = CanFrame(0, 8, [0, 0, 0, 0, 0, 0, 0, 0])
        while rev_num > 0:
            rev_num -= 1

            self.canLib.VCI_Receive(USBCAN1, 0, 0, pointer(vco_rx), 1, 1000)
            self.VCICANOBJ2CanFrame(vco_rx, can_frame)
            self.printCanFrame(can_frame)


    def printCanFrame(self, can_frame):
        print("CanId = %x DLC = %d  Data = " % (can_frame.can_id, can_frame.can_dlc), end="")
        for d in can_frame.can_data:
            print("%X " % d, end="")
        print()


    def VCICANOBJ2CanFrame(self, vco_can, can_frame):
        can_frame.can_id = vco_can.ID
        can_frame.can_dlc = vco_can.DataLen
        can_frame.can_data = list(vco_can.Data)

